<?php
namespace app\protocol;

use think\App;
use Workerman\Connection\TcpConnection;

class Router
{
    protected $app;
    protected $routes = [];
    protected $middlewares = [];

    public function __construct(App $app)
    {
        $this->app = $app;
        $this->registerDefaultRoutes();
    }

    /**
     * 注册默认路由
     */
    protected function registerDefaultRoutes(): void
    {
        $commands = config('protocol.commands', []);

        foreach ($commands as $command => $config) {
            $this->routes[$command] = [
                'handler' => $config['handler'],
                'description' => $config['description'],
                'pattern' => $this->getCommandPattern($command)
            ];
        }
    }

    /**
     * 获取命令模式正则
     */
    protected function getCommandPattern(string $command): ?string
    {
        $patterns = [
            'mul' => '/^mul\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)$/i',
            'incr' => '/^incr\s+(-?\d+(?:\.\d+)?)$/i',
            'div' => '/^div\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)$/i',
            'conv_tree' => '/^conv_tree/',
            'help' => '/^help(?:\s+(\w+))?$/i'
        ];

        return $patterns[$command] ?? null;
    }

    /**
     * 注册新命令
     */
    public function register(string $command, string $handler, string $description = '', string $pattern = null): self
    {
        $this->routes[$command] = [
            'handler' => $handler,
            'description' => $description,
            'pattern' => $pattern
        ];

        return $this;
    }

    /**
     * 路由匹配
     */
    public function match(string $input): array
    {
        $input = trim($input);
        if (empty($input)) {
            return ['found' => false, 'error' => '空命令'];
        }

        $parts = preg_split('/\s+/', $input, 2);
        $commandName = strtolower($parts[0]);
        $params = $parts[1] ?? '';

        if (!isset($this->routes[$commandName])) {
            return [
                'found' => false,
                'error' => "未知命令: '{$commandName}'，输入 'help' 查看可用命令"
            ];
        }

        $route = $this->routes[$commandName];

        // 模式匹配验证
        if (!empty($route['pattern']) && !preg_match($route['pattern'], $input)) {
            return [
                'found' => false,
                'error' => "参数格式错误，使用: {$route['description']}"
            ];
        }

        return [
            'found' => true,
            'command' => $commandName,
            'handler' => $route['handler'],
            'params' => $params,
            'description' => $route['description']
        ];
    }

    /**
     * 执行命令
     */
    public function dispatch(array $routeInfo, string $params, TcpConnection $connection): string
    {
        if (!$routeInfo['found']) {
            return "ERROR: " . $routeInfo['error'];
        }

        try {
            $handler = $this->resolveHandler($routeInfo['handler']);
            $result = $handler->execute($params, $connection);
            return "RESULT: " . $result;
        } catch (\InvalidArgumentException $e) {
            return "ERROR: " . $e->getMessage();
        } catch (\Exception $e) {
            return "ERROR: 服务器内部错误";
        }
    }

    /**
     * 解析处理器
     */
    protected function resolveHandler(string $handlerClass): CommandInterface
    {
        if (!class_exists($handlerClass)) {
            throw new \InvalidArgumentException("命令处理器不存在: {$handlerClass}");
        }

        $handler = $this->app->make($handlerClass);

        if (!$handler instanceof CommandInterface) {
            throw new \InvalidArgumentException("命令处理器必须实现 CommandInterface");
        }

        return $handler;
    }

    /**
     * 获取所有命令帮助
     */
    public function getHelp(): string
    {
        $help = "可用命令:\r\n";
        foreach ($this->routes as $command => $config) {
            $help .= "  " . str_pad($command, 12) . " - " . $config['description'] . "\r\n";
        }
        $help .= "输入 'help <命令名>' 查看具体用法\r\n";
        return $help;
    }

    /**
     * 获取命令详情
     */
    public function getCommandDetail(string $command): ?string
    {
        if (!isset($this->routes[$command])) {
            return null;
        }

        try {
            $handler = $this->resolveHandler($this->routes[$command]['handler']);
            return $handler::getDescription() . "\r\n用法: " . $handler::getUsage();
        } catch (\Exception $e) {
            return $this->routes[$command]['description'];
        }
    }

    /**
     * 获取所有注册的命令
     */
    public function getRoutes(): array
    {
        return $this->routes;
    }
}